/*
 * SvrTask.cpp
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */

#include "SvrTask.h"

SvrTask::SvrTask()
{
    Status = SV_INIT;
    svr_heartbeat_task = TASK_CLOSE;
    this->lock_flag = false;
}

SvrTask::~SvrTask()
{
	/*
	 * add your code here
	 * */
}

int SvrTask::init(SvrConfig * pconfig)
{
    if(pconfig == NULL)
        return FAILURE;

    this->pSvrconfig = pconfig;

    /*init buf list*/
	live_stream_task_list.init_list(true);
	free_live_stream_task_list.init_list(false);

	/*init stream config*/
	init_config_stream();

    return SUCCESS;
}

/*
*task data handle
*/
int SvrTask::handle_heartbeat_data(char * buf,size_t buf_len)
{
    if(buf == NULL || buf_len == 0 || buf_len > 64)
       return -1;

    /*hanld end*/
    return SUCCESS;
}

/*
*init config stream
*/
void SvrTask::init_config_stream(void)
{
	/*
	*check svr type ,only ,center server ,read stream config
	*/
	if(this->pSvrconfig->svrtype == 0)
	{
		return ;
	}

	/*
	 * read config file
	 **/
	TiXmlDocument configdoc;
	if(!configdoc.LoadFile(this->pSvrconfig->streamconfigfile))
	{
		return;
	}

	TiXmlHandle docHandle(&configdoc);
	TiXmlElement * xElement = NULL;
	printf("stream config:=========\r\n");
	xElement =  docHandle.FirstChildElement("list").FirstChildElement("stream").ToElement();
	while(xElement != NULL)
	{
		printf("%s,%s,%s,%s,%s\r\n",xElement->Attribute("id"),xElement->Attribute("fmt"),xElement->Attribute("ip"),xElement->Attribute("port"),xElement->Attribute("stream_name"));

		live_stream_task * task = NULL;
		this->alloc_stream_task(&task);

		task->id = atoi(xElement->Attribute("id"));
		task->stream_fmt = (HTTP_MIME)atoi(xElement->Attribute("fmt"));
		strcpy(task->remote_ip,xElement->Attribute("ip"));
		task->addr_port = atoi(xElement->Attribute("port"));
		strcpy(task->stream_name,xElement->Attribute("stream_name"));
		this->add_stream_task(task);

		xElement = xElement->NextSiblingElement();
	}
	printf("stream config end ==========\r\n");

	/*ok ,clear stream task*/
	this->clear_stream_task();
}

/*
*alloc new stream task
*/
void SvrTask::alloc_stream_task(live_stream_task ** task)
{
	taskLock.Lock();
	{
		if(free_live_stream_task_list.size() > 0)
		{
			free_live_stream_task_list.alloc(task);
		}
		else
		{
			*task = new live_stream_task();
		}
		taskLock.Unlock();
	}
}
/*
*reset_stream_task
*/
void SvrTask::reset_stream_task(live_stream_task * task)
{
	task->id = 0;
	memset(task->stream_name,'\0',FILE_MAX_PATH);
	memset(task->remote_ip,'\0',IP_LEN);
	task->addr_port = 0;
	task->flag = TASK_NONE;
	task->status = TASK_CLOSE;
	task->stream_enable = false;
	task->begin_time = time(NULL);
	task->end_time = time(NULL);
	task->ndelay_times = 0;
	task->ntry_times = 0;
}
/*
*free_stream_task
*/
void SvrTask::free_stream_task(live_stream_task * task)
{
	taskLock.Lock();
	{
		if(task != NULL)
		{
			reset_stream_task(task);
			free_live_stream_task_list.push(task);
		}
		taskLock.Unlock();
	}
}
/*
*add_stream_task
*/
void SvrTask::add_stream_task(live_stream_task * task)
{
	if(task == NULL)
		return ;

	taskLock.Lock();
	{
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c >0)
		{
			if(ptask->id == task->id)
			{
				break;
			}

			ptask = ptask->next;
			c --;
		}

		if(ptask != NULL)
		{
			/*update task*/
			memset(ptask->stream_name,'\0',FILE_MAX_PATH);
			memset(ptask->remote_ip,'\0',IP_LEN);
			strcpy(ptask->stream_name,task->stream_name);
			strcpy(ptask->remote_ip,task->remote_ip);
			ptask->addr_port = task->addr_port;
			ptask->stream_fmt = task->stream_fmt;
			ptask->flag = TASK_MARKER;
			/*free*/
			this->free_live_stream_task_list.push(task);
		}
		else
		{
			task->flag = TASK_ADD;
			live_stream_task_list.push(task);
		}
		taskLock.Unlock();
	}
}
/*
*close_stream_task
*if return 0,means close completed
*else return < 0 means close in the next.
*/
int SvrTask::close_stream_task(uint16_t id)
{
	int ret = 0;
	taskLock.Lock();
	{
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c > 0)
		{
			if(ptask->id == id)
			{
				ptask->status = TASK_CLOSE;
				ptask->stream_enable = false;
				ptask->end_time = time(NULL);
				if(ptask->ntry_times < 10)
				{
                    ptask->ntry_times++;
				}
				/*check is del flag*/
				if(ptask->flag == TASK_DEL)
				{
					/*
					*del clip
					*/
					int error;
					DataClip::del_clip_file_list(ptask->id,ptask->stream_fmt,this->pSvrconfig->store_clip_days,this->pSvrconfig->liverootpath,error);

					/*
					*free buf
					*/
					live_stream_task_list.remove(ptask);
					reset_stream_task(ptask);
					free_live_stream_task_list.push(ptask);
					ret = -1;
				}
				/*end*/
				break;
			}

			ptask = ptask->next;
			c --;
		}

		taskLock.Unlock();
	}
	return ret;
}
/*
*enable_stream_task
*/
void SvrTask::enable_stream_task(uint16_t id)
{
	taskLock.Lock();
	{
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c > 0)
		{
			if(ptask->id == id)
			{
				ptask->stream_enable = true;
				ptask->ntry_times = 0;
				ptask->ndelay_times = 0;
				break;
			}

			ptask = ptask->next;
			c --;
		}

		taskLock.Unlock();
	}
}
/*
*find stream id
*/
uint16_t SvrTask::find_stream_id(char * sname)
{
	if(sname == NULL)
		return 0;

	if(strlen(sname) == 0)
		return 0;

	uint16_t id = 0;
	taskLock.Lock();
	{
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c > 0)
		{
			if(strcmp(ptask->stream_name,sname) == 0)
			{
				id = ptask->id;
				break;
			}

			ptask = ptask->next;
			c --;
		}

		taskLock.Unlock();
	}

	return id;
}
/*
*check_stream_task_is_exit
*/
bool SvrTask::check_stream_task_is_exit(uint16_t id)
{
	bool ret = false;
	taskLock.Lock();
	{
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c > 0)
		{
			if(ptask->id == id)
			{
				ret = true;

				/*
				*check del flag,and
				*/
				if(ptask->flag == TASK_DEL)
				{
					/*
					*del clip
					*/
					int error;
					DataClip::del_clip_file_list(ptask->id,ptask->stream_fmt,this->pSvrconfig->store_clip_days,this->pSvrconfig->liverootpath,error);

					/*
					*free buf
					*/
					live_stream_task_list.remove(ptask);
					reset_stream_task(ptask);
					free_live_stream_task_list.push(ptask);
					ret = false;
				}

				/*end*/
				break;
			}
			ptask = ptask->next;
			c --;
		}

		taskLock.Unlock();
	}

	return ret;
}
/*
*clear_stream_task
*/
void SvrTask::clear_stream_task(void)
{
	taskLock.Lock();
	{
		stack<live_stream_task *> del_list;
		live_stream_task * ptask = live_stream_task_list.get_first();
		int c = live_stream_task_list.size();
		while(ptask != NULL && c > 0)
		{
			if(ptask->flag == TASK_NONE)
			{
				/*
				*set to del flag
				*/
				if(ptask->ndelay_times > 30)
				{
					ptask->flag = TASK_DEL;
				}
				else
				{
					ptask->ndelay_times++;
				}
			}
			else
			{
				ptask->flag = TASK_NONE;
			}

			/*
			*clear clip file,at every 5 hours
			*/
			int error = 0;
			DataClip::del_clip_file_list(ptask->id,ptask->stream_fmt,this->pSvrconfig->store_clip_days,this->pSvrconfig->liverootpath,error);

			/*next*/
			ptask = ptask->next;
			c --;
		}
		taskLock.Unlock();
	}
}

/*
*use it must be carefull
*task_list_lock, lock do enter call,
*when you usr completed,then call end_enter
*/
live_stream_task * SvrTask::begin_enter(void)
{
	live_stream_task * pnode = NULL;
	taskLock.Lock();
	pnode =  live_stream_task_list.get_first();
	lock_flag = true;
	return pnode;

}

void SvrTask::end_enter(void)
{
	taskLock.Unlock();
	lock_flag = false;
}
